﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace Exentials.Xoox
{
    /// <summary>
    /// Implement a collection of XElementBase type
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class XElementSequenceContainer<T> : XElementBase, IEnumerable<T> where T : XElementBase
    {
        private List<T> _elements;

        public XElementSequenceContainer(string tag)
            : base(tag)
        {
            _elements = new List<T>();
        }

        internal void Add(T item)
        {
            ISequence index = item as ISequence;
            if (index == null) throw new XException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Item is null or does not implement {0} interface", typeof(ISequence)));

            if (_elements.Exists(t => (t as ISequence).Index == index.Index)) throw new XException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Item index {0} already exist", index.Index));

            XElementBase child;
            if ((child = _elements.Where(t => (t as ISequence).Index < index.Index).OrderBy(t => (t as ISequence).Index).LastOrDefault()) != null)
            {
                child.GetXElement().AddAfterSelf(item.GetXElement());
            }
            else if ((child = _elements.Where(t => (t as ISequence).Index > index.Index).OrderBy(t => (t as ISequence).Index).FirstOrDefault()) != null)
            {
                child.GetXElement().AddBeforeSelf(item.GetXElement());
            }
            else
                base.Add(item);

            _elements.Add(item);
        }

        public virtual T this[int index]
        {
            get
            {
                return _elements.FirstOrDefault(t => (t as ISequence).Index == index);
            }
        }

        #region IEnumerable<T> Members

        public IEnumerator<T> GetEnumerator()
        {
            return _elements.OrderBy(t => (t as ISequence).Index).GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion
    }
}
